home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.5 Applications 2004 April / SGI IRIX 6.5 Applications 2004 April.iso / dist / mozilla.idb / var / netscape / mozilla / chrome / toolkit.jar.z / toolkit.jar / content / global / nsDragAndDrop.js < prev    next >
Text File  |  2003-11-11  |  12KB  |  314 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: NPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Netscape Public License
  6.  * Version 1.1 (the "License"); you may not use this file except in
  7.  * compliance with the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/NPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is 
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 1998
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *   Ben Goodger <ben@netscape.com> (Original Author)
  24.  *   Pierre Chanial <pierrechanial@netscape.net>
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either the GNU General Public License Version 2 or later (the "GPL"), or 
  28.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the NPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the NPL, the GPL or the LGPL.
  37.  *
  38.  * ***** END LICENSE BLOCK ***** */
  39.  
  40. ////////////////////////////////////////////////////////////////////////////
  41. // XXX - WARNING - DRAG AND DROP API CHANGE ALERT - XXX
  42. // This file has been extensively modified in a checkin planned for Mozilla
  43. // 0.8, and the API has been modified. DO NOT MODIFY THIS FILE without 
  44. // approval from ben@netscape.com, otherwise your changes will be lost. 
  45.  
  46. /**
  47.  * XXX - until load is supported in chrome, you also need to include 
  48.  *       these files:
  49.  *       chrome://global/content/nsTransferable.js
  50.  **/
  51.  
  52.  
  53.  
  54. /**
  55.  * nsDragAndDrop - a convenience wrapper for nsTransferable, nsITransferable
  56.  *                 and nsIDragService/nsIDragSession. 
  57.  *
  58.  * USAGE INFORMATION: see 'README-nsDragAndDrop.html' in the same source directory
  59.  *                    as this file (typically xpfe/global/resources/content)
  60.  */
  61.  
  62. var nsDragAndDrop = {
  63.   
  64.   _mDS: null,
  65.   get mDragService()
  66.     {
  67.       if (!this._mDS) 
  68.         {
  69.           const kDSContractID = "@mozilla.org/widget/dragservice;1";
  70.           const kDSIID = Components.interfaces.nsIDragService;
  71.           this._mDS = Components.classes[kDSContractID].getService(kDSIID);
  72.         }
  73.       return this._mDS;
  74.     },
  75.  
  76.   /**
  77.    * void startDrag (DOMEvent aEvent, Object aDragDropObserver) ;
  78.    *
  79.    * called when a drag on an element is started.
  80.    *
  81.    * @param DOMEvent aEvent
  82.    *        the DOM event fired by the drag init
  83.    * @param Object aDragDropObserver
  84.    *        javascript object of format described above that specifies
  85.    *        the way in which the element responds to drag events.
  86.    **/  
  87.   startDrag: function (aEvent, aDragDropObserver)
  88.     {
  89.       if (!("onDragStart" in aDragDropObserver))
  90.         return;
  91.  
  92.       const kDSIID = Components.interfaces.nsIDragService;
  93.       var dragAction = { action: kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_MOVE + kDSIID.DRAGDROP_ACTION_LINK };
  94.  
  95.       var transferData = { data: null };
  96.       try 
  97.         {
  98.           aDragDropObserver.onDragStart(aEvent, transferData, dragAction);
  99.         }
  100.       catch (e) 
  101.         {
  102.           return;  // not a draggable item, bail!
  103.         }
  104.  
  105.       if (!transferData.data) return;
  106.       transferData = transferData.data;
  107.       
  108.       var transArray = Components.classes["@mozilla.org/supports-array;1"]
  109.                                  .createInstance(Components.interfaces.nsISupportsArray);
  110.  
  111.       var region = null;
  112.       if (aEvent.originalTarget.localName == "treechildren") {
  113.         // let's build the drag region
  114.         var tree = aEvent.originalTarget.parentNode;
  115.         try {
  116.           region = Components.classes["@mozilla.org/gfx/region;1"].createInstance(Components.interfaces.nsIScriptableRegion);
  117.           region.init();
  118.           var obo = tree.treeBoxObject;
  119.           var bo = obo.treeBody.boxObject;
  120.           var obosel= obo.selection;
  121.  
  122.           var rowX = bo.x;
  123.           var rowY = bo.y;
  124.           var rowHeight = obo.rowHeight;
  125.           var rowWidth = bo.width;
  126.  
  127.           //add a rectangle for each visible selected row
  128.           for (var i = obo.getFirstVisibleRow(); i <= obo.getLastVisibleRow(); i ++)
  129.           {
  130.             if (obosel.isSelected(i))
  131.               region.unionRect(rowX, rowY, rowWidth, rowHeight);
  132.             rowY = rowY + rowHeight;
  133.           }
  134.       
  135.           //and finally, clip the result to be sure we don't spill over...
  136.           region.intersectRect(bo.x, bo.y, bo.width, bo.height);
  137.         } catch(ex) {
  138.           dump("Error while building selection region: " + ex + "\n");
  139.           region = null;
  140.         }
  141.       }
  142.  
  143.       var count = 0;
  144.       do 
  145.         {
  146.           var trans = nsTransferable.set(transferData._XferID == "TransferData" 
  147.                                          ? transferData 
  148.                                          : transferData.dataList[count++]);
  149.           transArray.AppendElement(trans.QueryInterface(Components.interfaces.nsISupports));
  150.         }
  151.       while (transferData._XferID == "TransferDataSet" && 
  152.              count < transferData.dataList.length);
  153.       
  154.       try {
  155.         this.mDragService.invokeDragSession(aEvent.target, transArray, region, dragAction.action);
  156.       }
  157.       catch(ex) {
  158.         // this could be because the user pressed escape to
  159.         // cancel the drag. even if it's not, there's not much
  160.         // we can do, so be silent.
  161.       }
  162.       aEvent.preventBubble();
  163.     },
  164.  
  165.   /** 
  166.    * void dragOver (DOMEvent aEvent, Object aDragDropObserver) ;
  167.    *
  168.    * called when a drag passes over this element
  169.    *
  170.    * @param DOMEvent aEvent
  171.    *        the DOM event fired by passing over the element
  172.    * @param Object aDragDropObserver
  173.    *        javascript object of format described above that specifies
  174.    *        the way in which the element responds to drag events.
  175.    **/
  176.   dragOver: function (aEvent, aDragDropObserver)
  177.     { 
  178.       if (!("onDragOver" in aDragDropObserver)) 
  179.         return;
  180.       if (!this.checkCanDrop(aEvent, aDragDropObserver))
  181.         return;
  182.       var flavourSet = aDragDropObserver.getSupportedFlavours();
  183.       for (var flavour in flavourSet.flavourTable)
  184.         {
  185.           if (this.mDragSession.isDataFlavorSupported(flavour))
  186.             {
  187.               aDragDropObserver.onDragOver(aEvent, 
  188.                                            flavourSet.flavourTable[flavour], 
  189.                                            this.mDragSession);
  190.               aEvent.preventBubble();
  191.               break;
  192.             }
  193.         }
  194.     },
  195.  
  196.   mDragSession: null,
  197.  
  198.   /** 
  199.    * void drop (DOMEvent aEvent, Object aDragDropObserver) ;
  200.    *
  201.    * called when the user drops on the element
  202.    *
  203.    * @param DOMEvent aEvent
  204.    *        the DOM event fired by the drop
  205.    * @param Object aDragDropObserver
  206.    *        javascript object of format described above that specifies
  207.    *        the way in which the element responds to drag events.
  208.    **/
  209.   drop: function (aEvent, aDragDropObserver)
  210.     {
  211.       if (!("onDrop" in aDragDropObserver))
  212.         return;
  213.       if (!this.checkCanDrop(aEvent, aDragDropObserver))
  214.         return;  
  215.       if (this.mDragSession.canDrop) {
  216.         var flavourSet = aDragDropObserver.getSupportedFlavours();
  217.         var transferData = nsTransferable.get(flavourSet, this.getDragData, true);
  218.         // hand over to the client to respond to dropped data
  219.         var multiple = "canHandleMultipleItems" in aDragDropObserver && aDragDropObserver.canHandleMultipleItems;
  220.         var dropData = multiple ? transferData : transferData.first.first;
  221.         aDragDropObserver.onDrop(aEvent, dropData, this.mDragSession);
  222.       }
  223.       aEvent.preventBubble();
  224.     },
  225.  
  226.   /** 
  227.    * void dragExit (DOMEvent aEvent, Object aDragDropObserver) ;
  228.    *
  229.    * called when a drag leaves this element
  230.    *
  231.    * @param DOMEvent aEvent
  232.    *        the DOM event fired by leaving the element
  233.    * @param Object aDragDropObserver
  234.    *        javascript object of format described above that specifies
  235.    *        the way in which the element responds to drag events.
  236.    **/
  237.   dragExit: function (aEvent, aDragDropObserver)
  238.     {
  239.       if (!this.checkCanDrop(aEvent, aDragDropObserver))
  240.         return;
  241.       if ("onDragExit" in aDragDropObserver)
  242.         aDragDropObserver.onDragExit(aEvent, this.mDragSession);
  243.     },  
  244.     
  245.   /** 
  246.    * void dragEnter (DOMEvent aEvent, Object aDragDropObserver) ;
  247.    *
  248.    * called when a drag enters in this element
  249.    *
  250.    * @param DOMEvent aEvent
  251.    *        the DOM event fired by entering in the element
  252.    * @param Object aDragDropObserver
  253.    *        javascript object of format described above that specifies
  254.    *        the way in which the element responds to drag events.
  255.    **/
  256.   dragEnter: function (aEvent, aDragDropObserver)
  257.     {
  258.       if (!this.checkCanDrop(aEvent, aDragDropObserver))
  259.         return;
  260.       if ("onDragEnter" in aDragDropObserver)
  261.         aDragDropObserver.onDragEnter(aEvent, this.mDragSession);
  262.     },  
  263.     
  264.   /** 
  265.    * nsISupportsArray getDragData (Object aFlavourList)
  266.    *
  267.    * Creates a nsISupportsArray of all droppable items for the given
  268.    * set of supported flavours.
  269.    * 
  270.    * @param FlavourSet aFlavourSet
  271.    *        formatted flavour list.
  272.    **/  
  273.   getDragData: function (aFlavourSet)
  274.     {
  275.       var supportsArray = Components.classes["@mozilla.org/supports-array;1"]
  276.                                     .createInstance(Components.interfaces.nsISupportsArray);
  277.  
  278.       for (var i = 0; i < nsDragAndDrop.mDragSession.numDropItems; ++i)
  279.         {
  280.           var trans = nsTransferable.createTransferable();
  281.           for (var j = 0; j < aFlavourSet.flavours.length; ++j)
  282.             trans.addDataFlavor(aFlavourSet.flavours[j].contentType);
  283.           nsDragAndDrop.mDragSession.getData(trans, i);
  284.           supportsArray.AppendElement(trans);
  285.         }
  286.       return supportsArray;
  287.     },
  288.  
  289.   /** 
  290.    * Boolean checkCanDrop (DOMEvent aEvent, Object aDragDropObserver) ;
  291.    *
  292.    * Sets the canDrop attribute for the drag session.
  293.    * returns false if there is no current drag session.
  294.    *
  295.    * @param DOMEvent aEvent
  296.    *        the DOM event fired by the drop
  297.    * @param Object aDragDropObserver
  298.    *        javascript object of format described above that specifies
  299.    *        the way in which the element responds to drag events.
  300.    **/
  301.   checkCanDrop: function (aEvent, aDragDropObserver)
  302.     {
  303.       if (!this.mDragSession) 
  304.         this.mDragSession = this.mDragService.getCurrentSession();
  305.       if (!this.mDragSession) 
  306.         return false;
  307.       this.mDragSession.canDrop = this.mDragSession.sourceNode != aEvent.target;
  308.       if ("canDrop" in aDragDropObserver)
  309.         this.mDragSession.canDrop &= aDragDropObserver.canDrop(aEvent, this.mDragSession);
  310.       return true;
  311.     } 
  312. };
  313.  
  314.